// Copyright (c) 2020-present,  INSPUR Co, Ltd.  All rights reserved.
// This source code is licensed under Apache 2.0 License.

#pragma once
#include <cstddef>
#include <list>
#include <thread>
#include <unordered_set>

#include "arena_handle_event.h"
#include "range_arena_rebuild.h"
#include "range_arena.h"
#include "memtable/skiplist.h"
#include "pure_mem/rangearena/thread_safe_queue.h"

namespace rocksdb {
struct EVENT;
class MultiRangeArena;
class MultiRangeManager {
 public:
  explicit MultiRangeManager(void* multi_range);

  ~MultiRangeManager();
  // Event + Event to do
  struct EVENT {
    RangeArena* range_arena;
    RangeArenaEvent op;
    EVENT(RangeArena* arena, RangeArenaEvent arena_event)
        : range_arena(arena), op(arena_event) {}
  };

  //MultiRangeArena* MultiRange() { return static_cast<MultiRangeArena *>(multi_range_); }

  void AcceptEvent(RangeArena* cur, RangeArenaEvent op);

  //size_t GetEventNum() const ;

  void ThreadRun();

  // Memory block expand/decompose when the memory block space is full,
  // the memory block needs to be handled
  void Handle(RangeArena* current_range_arena);

  static int UserKeyCompare(const Slice& a, const Slice& b);

  static size_t GetNodeKVSize(const char* buf);
  void GenNodeList(RangeArena* current_rangearena, std::list<void*>& list,
                   size_t& data_num);
  void PutNodeListIntoNewBlock(RangeArena* ra, std::list<void*>& list);
  static RangeArena* NewBlock(size_t data_num, Slice& start, Slice& end, Logger* info_log);
//  void GenNewArtNodeSet(RangeArena* currentRangeArena, std::list<void*>& list,
//                        size_t& cur_data_num,
//                        std::unordered_set<void*>& nodeStoredNew);

 private:
    static size_t exceptedNewBlockNum(size_t cur_data_num);
    size_t kvDataSplit(size_t block_mid_size, std::list<void *>& list_cur_art,
                    std::vector<std::list<void *>>& list_block,
                    std::vector<Slice>& start, std::vector<Slice>& end,
                    std::vector<size_t>& data_num);

  std::thread event_process_;
  void* multi_range_;
  bool closed_ = false;
  ThreadSafeQueue<EVENT> events_;
};

}  // namespace rocksdb
